#include "pluginmanager.h"
#include "pluginprocess.h"

#include <QProcess>
#include <QStringList>
#include <QDebug>
#include <QDir>
#include <QDomDocument>

// for now - change this depending on your platofrm - eventually there needs to be a system-wide config file with
// this sort of stuff in it:
//
// Even better - we can get QMake to check for the presence of python and set a preprocessor directive for us.
//
// Even even more betterer: this should be set in the config for this tool, and the default should be the above.
#ifdef Q_OS_LINUX
#define PYTHONPATH "/usr/bin/python"
#else
#define PYTHONPATH "C:/Python/python.exe"
#endif

QString CPluginManager::getLibDir() const
{
	return m_strLibDir;
}

void CPluginManager::setLibDir(const QString &strLibDir)
{
	m_strLibDir = strLibDir;
}

QString CPluginManager::getPluginDir() const
{
	return m_strPluginDir;
}

void CPluginManager::setPluginDir(const QString &strPluginDir)
{
	m_strPluginDir = strPluginDir;
}

void CPluginManager::scanPlugins()
{
	// scan plugins uses the python lib code to get an XML document containing all the information required to list the plugins.

	// create the QProcess to run the python code:
	// we need to set the PYTHONPATH environment variable to be the directory that contains our module helper
	// library.
	QProcess proc;
	QStringList env;
	env << QString("PYTHONPATH=%1").arg(m_strLibDir);
	proc.setEnvironment(env);


	// get the python interpreter:
	QString strPythonPath(PYTHONPATH);
	// create command line arguments:
	QStringList args;

	// check that the lib directory exists in debug builds:
	QDir libDir(m_strLibDir);
	Q_ASSERT(libDir.exists());

	args << libDir.absoluteFilePath("pluginManager.py") << "--printConfig" << m_strPluginDir;


	proc.start(strPythonPath, args);
	if (! proc.waitForFinished())
	{
		Q_ASSERT_X(0, Q_FUNC_INFO, "Could not run python lib code");
		return;
	}

	QString strDoc = proc.readAllStandardOutput();
	QDomDocument pluginDoc;
	QString strError;
	int nErrorLine, nErrorCol;

	if (!pluginDoc.setContent(strDoc, &strError, &nErrorLine, &nErrorCol))
	{
	qDebug() << "Error:" << strError << nErrorLine << nErrorCol;
	qDebug() << "stdout was:" << strDoc;
	qDebug() << "stderr was:" << proc.readAllStandardError();
	}

	m_pluginConfig = pluginDoc;
	QDomElement docElem = pluginDoc.documentElement();
	QDomNodeList plugins = docElem.elementsByTagName("plugin");

	qDebug() << "Found" << plugins.size() << "plugins:";
	for (int i = 0; i < plugins.size(); i++)
	{
	addPlugin(plugins.at(i).toElement());
	}
}

CPluginProcess *CPluginManager::runScannerPlugins(const QString &strInputFilePath, const QStringList &slPluginNames, const QString &strConfigFile )
{
	// make new plugin object:
	CPluginProcess *plug = new CPluginProcess();

	QStringList env;
	env << QString("PYTHONPATH=%1").arg(m_strLibDir);
	plug->setEnvironment(env);


	// get the python interpreter:
	QString strPythonPath(PYTHONPATH);
	// create command line arguments:
	QStringList args;

	// check that the lib directory exists in debug builds:
	QDir libDir(m_strLibDir);
	Q_ASSERT(libDir.exists());

	args << libDir.absoluteFilePath("pluginManager.py")
		<< "--runPlugins"
		<< QString("%1").arg(slPluginNames.join(","))
		<< strInputFilePath
		<< strConfigFile
		<< m_strPluginDir;

	plug->start(strPythonPath, args);

	return plug;
}

void CPluginManager::addPlugin(const QDomElement &pluginXML)
{
	// TODO - this is very cheesy - perhaps clean it up later?
	QString strName = pluginXML.firstChildElement("name").text().trimmed();
	QString strDesc = pluginXML.firstChildElement("description").text().trimmed();
	QString strType = pluginXML.firstChildElement("type").text().trimmed();

	m_pluginDetails[strName] = QPair<QString,QString>(strDesc, strType);

	qDebug() << "Plugin details: " << strName << strType << strDesc;
}

QString CPluginManager::getPluginDescription(const QString &strPluginName) const
{
	if (m_pluginDetails.contains(strPluginName))
	{
	return m_pluginDetails[strPluginName].first;
	}
	return QString();
}

QString CPluginManager::getPluginType(const QString &strPluginName) const
{
	if (m_pluginDetails.contains(strPluginName))
	{
	return m_pluginDetails[strPluginName].second;
	}
	return QString();
}

CPluginManager::CPluginManager()
{
}

CPluginManager * CPluginManager::getPluginManager()
{
	static CPluginManager pm;
	return &pm;
}

QString CPluginManager::getPluginConfig() const
{
	return m_pluginConfig.toString();
}
